/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.drawee.generic;

import static com.facebook.drawee.drawable.ScalingUtils.ScaleType;
import com.facebook.drawee.drawable.AutoRotateDrawable;
import com.facebook.imagepipeline.systrace.FrescoSystrace;
import com.facebook.infer.annotation.ReturnsOwnership;
import com.oszc.bbhmlibrary.utils.LogUtil;
import com.oszc.bbhmlibrary.utils.ResUtil;
import ohos.agp.components.Attr;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Image;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.ResourceManager;

import javax.annotation.Nullable;
import java.io.IOException;

/**
 * Inflater for the {@code GenericDraweeHierarchy}.
 *
 * <p>Fading animation parameters:
 *
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_fadeDuration Aspect ratio parameters:
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_viewAspectRatio Images & scale types
 *     parameters:
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_placeholderImage
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_placeholderImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_retryImage
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_retryImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_failureImage
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_failureImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_progressBarImage
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_progressBarImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_progressBarAutoRotateInterval
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_actualImageScaleType
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_backgroundImage
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_overlayImage
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_pressedStateOverlayImage Rounding
 *     parameters:
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundAsCircle
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundedCornerRadius
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundTopLeft
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundTopRight
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundBottomRight
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundBottomLeft
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundTopStart
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundTopEnd
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundBottomStart
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundBottomEnd
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundWithOverlayColor
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundingBorderWidth
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundingBorderColor
 * @attr ref com.facebook.R.styleable#GenericDraweeHierarchy_roundingBorderPadding
 */
public class GenericDraweeHierarchyInflater {
  private final static String TAG = GenericDraweeHierarchyInflater.class.getSimpleName();
  public static String attr_fadeDuration = "fadeDuration";
  public static String attr_viewAspectRatio= "viewAspectRatio";
  public static String attr_placeholderImage= "placeholderImage";
  public static String attr_placeholderImageScaleType= "placeholderImageScaleType";
  public static String attr_retryImage= "retryImage";
  public static String attr_retryImageScaleType = "retryImageScaleType";
  public static String attr_failureImage = "failureImage";
  public static String attr_failureImageScaleType = "failureImageScaleType";
  public static String attr_progressBarImage = "progressBarImage";
  public static String attr_progressBarImageScaleType = "progressBarImageScaleType";
  public static String attr_progressBarAutoRotateInterval = "progressBarAutoRotateInterval";
  public static String attr_actualImageScaleType = "actualImageScaleType";
  public static String attr_backgroundImage = "backgroundImage";
  public static String attr_overlayImage = "overlayImage";
  public static String attr_pressedStateOverlayImage = "pressedStateOverlayImage";
  public static String attr_roundAsCircle = "roundAsCircle";
  public static String attr_roundedCornerRadius = "roundedCornerRadius";
  public static String attr_roundTopLeft = "roundTopLeft";
  public static String attr_roundTopRight = "roundTopRight";
  public static String attr_roundBottomRight = "roundBottomRight";
  public static String attr_roundBottomLeft = "roundBottomLeft";
  public static String attr_roundTopStart = "roundTopStart";
  public static String attr_roundTopEnd = "roundTopEnd";
  public static String attr_roundBottomStart = "roundBottomStart";
  public static String attr_roundBottomEnd = "roundBottomEnd";
  public static String attr_roundWithOverlayColor = "roundWithOverlayColor";
  public static String attr_roundingBorderWidth = "roundingBorderWidth";
  public static String attr_roundingBorderColor = "roundingBorderColor";
  public static String attr_roundingBorderPadding = "roundingBorderPadding";


  /** Inflates a new hierarchy from XML. */
  public static GenericDraweeHierarchy inflateHierarchy(
          Context context, @Nullable AttrSet attrs, Image component) {
    return inflateBuilder(context, attrs).build(component);
  }

  /**
   * Inflates a new hierarchy builder from XML. The builder can then be modified in order to
   * override XML attributes if necessary.
   */
  public static GenericDraweeHierarchyBuilder inflateBuilder(
          Context context, @Nullable AttrSet attrs) {
    LogUtil.error(TAG,"inflateBuilder");
    if (FrescoSystrace.isTracing()) {
      FrescoSystrace.beginSection("GenericDraweeHierarchyBuilder#inflateBuilder");
    }
    ResourceManager resources = context.getResourceManager();
    GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(resources);
    builder = updateBuilder(builder, context, attrs);
    if (FrescoSystrace.isTracing()) {
      FrescoSystrace.endSection();
    }
    return builder;
  }

  /**
   * Updates the existing hierarchy builder based on the XML attributes.
   *
   * <p>This method is useful if a custom view uses different default values. In that case a builder
   * with adjusted default values can be passed to this method and only the properties explicitly
   * specified in XML will be overridden. The builder can be modified afterwards in case some XML
   * attributes needs to be overridden.
   *
   * @param builder a hierarchy builder to be updated
   * @return the modified instance of the same builder
   */
  public static GenericDraweeHierarchyBuilder updateBuilder(
      GenericDraweeHierarchyBuilder builder, Context context, @Nullable AttrSet attrs) {
    LogUtil.error(TAG,"updateBuilder A");
    // these paramters cannot be applied immediately so we store them first
    int progressBarAutoRotateInterval = 0;
    int roundedCornerRadius = 0;
    boolean roundTopLeft = true;
    boolean roundTopRight = true;
    boolean roundBottomLeft = true;
    boolean roundBottomRight = true;
    boolean roundTopStart = true;
    boolean roundTopEnd = true;
    boolean roundBottomStart = true;
    boolean roundBottomEnd = true;

    if (attrs != null) {
      LogUtil.error(TAG,"updateBuilder B1");
      attrs.getAttr(attr_actualImageScaleType).ifPresent(val -> builder.setActualImageScaleType(getScaleTypeFromXml(val.getIntegerValue())));
      LogUtil.error(TAG,"updateBuilder B2");
      attrs.getAttr(attr_placeholderImage).ifPresent(val -> builder.setPlaceholderImage(val.getElement()));
      attrs.getAttr(attr_placeholderImageScaleType).ifPresent(val -> builder.setPlaceholderImageScaleType(getScaleTypeFromXml(val.getIntegerValue())));
      LogUtil.error(TAG,"updateBuilder C1");
      attrs.getAttr(attr_pressedStateOverlayImage).ifPresent(val -> builder.setPressedStateOverlay(val.getElement()));
      attrs.getAttr(attr_progressBarImage).ifPresent(val -> builder.setProgressBarImage(val.getElement()));
      attrs.getAttr(attr_fadeDuration).ifPresent(val -> builder.setFadeDuration(val.getIntegerValue()));
      attrs.getAttr(attr_viewAspectRatio).ifPresent(val -> builder.setDesiredAspectRatio(val.getFloatValue()));
      LogUtil.error(TAG,"updateBuilder C2");
      LogUtil.error(TAG,"updateBuilder C3");
      attrs.getAttr(attr_retryImage).ifPresent(val -> builder.setRetryImage(val.getElement()));
      attrs.getAttr(attr_retryImageScaleType).ifPresent(val -> builder.setRetryImageScaleType(getScaleTypeFromXml(val.getIntegerValue())));
      LogUtil.error(TAG,"updateBuilder C4");
      
      attrs.getAttr(attr_failureImage).ifPresent(val -> builder.setFailureImage(val.getElement()));
      attrs.getAttr(attr_failureImageScaleType).ifPresent(val -> builder.setFailureImageScaleType(getScaleTypeFromXml(val.getIntegerValue())));
      attrs.getAttr(attr_progressBarImageScaleType).ifPresent(val -> builder.setProgressBarImageScaleType(getScaleTypeFromXml(val.getIntegerValue())));
      LogUtil.error(TAG,"updateBuilder C5");
      if (attrs.getAttr(attr_progressBarAutoRotateInterval).isPresent()) {
        Attr attr = attrs.getAttr(attr_progressBarAutoRotateInterval).get();
        progressBarAutoRotateInterval = attr.getIntegerValue();
      }
      LogUtil.error(TAG,"updateBuilder D");
      attrs.getAttr(attr_backgroundImage).ifPresent(val -> builder.setBackground(val.getElement()));
      attrs.getAttr(attr_overlayImage).ifPresent(val -> builder.setOverlay(val.getElement()));
      attrs.getAttr(attr_roundAsCircle).ifPresent(val -> getRoundingParams(builder).setRoundAsCircle(val.getBoolValue()));
      if (attrs.getAttr(attr_roundedCornerRadius).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundedCornerRadius).get();
        roundedCornerRadius = attr.getDimensionValue();
      }
      if (attrs.getAttr(attr_roundTopLeft).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundTopLeft).get();
        roundTopLeft = attr.getBoolValue();
      }
      if (attrs.getAttr(attr_roundTopRight).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundTopRight).get();
        roundTopRight = attr.getBoolValue();
      }

      if (attrs.getAttr(attr_roundBottomLeft).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundBottomLeft).get();
        roundBottomLeft = attr.getBoolValue();
      }

      if (attrs.getAttr(attr_roundBottomRight).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundBottomRight).get();
        roundBottomRight = attr.getBoolValue();
      }

      if (attrs.getAttr(attr_roundTopStart).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundTopStart).get();
        roundTopStart = attr.getBoolValue();

      }
      if (attrs.getAttr(attr_roundTopEnd).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundTopEnd).get();
        roundTopEnd = attr.getBoolValue();
      }
      if (attrs.getAttr(attr_roundBottomStart).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundBottomStart).get();
        roundBottomStart = attr.getBoolValue();
      }
      if (attrs.getAttr(attr_roundBottomEnd).isPresent()) {
        Attr attr = attrs.getAttr(attr_roundBottomEnd).get();
        roundBottomEnd = attr.getBoolValue();
      }
      LogUtil.error(TAG,"updateBuilder F");
      attrs.getAttr(attr_roundWithOverlayColor).ifPresent(val -> getRoundingParams(builder).setOverlayColor(val.getColorValue().getValue()));
      attrs.getAttr(attr_roundingBorderWidth).ifPresent(val -> getRoundingParams(builder).setBorderWidth(val.getDimensionValue()));
      attrs.getAttr(attr_roundingBorderColor).ifPresent(val -> getRoundingParams(builder).setBorderColor(val.getColorValue().getValue()));
      attrs.getAttr(attr_roundingBorderPadding).ifPresent(val -> getRoundingParams(builder).setPadding(val.getDimensionValue()));
      roundTopLeft = roundTopLeft && roundTopEnd;
      roundTopRight = roundTopRight && roundTopStart;
      roundBottomRight = roundBottomRight && roundBottomStart;
      roundBottomLeft = roundBottomLeft && roundBottomEnd;
    }

    LogUtil.error(TAG,"updateBuilder G");
    // wrap progress bar if auto-rotating requested
    if (builder.getProgressBarImage() != null && progressBarAutoRotateInterval > 0) {
      builder.setProgressBarImage(
          new AutoRotateDrawable(builder.getProgressBarImage(), progressBarAutoRotateInterval));
    }

    // set rounded corner radii if requested
    if (roundedCornerRadius > 0) {
      getRoundingParams(builder)
          .setCornersRadii(
              roundTopLeft ? roundedCornerRadius : 0,
              roundTopRight ? roundedCornerRadius : 0,
              roundBottomRight ? roundedCornerRadius : 0,
              roundBottomLeft ? roundedCornerRadius : 0);
    }
    LogUtil.error(TAG,"updateBuilder end");
    return builder;
  }

  @ReturnsOwnership
  private static RoundingParams getRoundingParams(GenericDraweeHierarchyBuilder builder) {
    if (builder.getRoundingParams() == null) {
      builder.setRoundingParams(new RoundingParams());
    }
    return builder.getRoundingParams();
  }

  @Nullable
  private static Element getDrawable(Context context, int resourceId) {
    try {
      return  new PixelMapElement(ResUtil.createByResourceId(context.getResourceManager(),resourceId,""));
    } catch (IOException | NotExistException e) {
      e.printStackTrace();
    }
    return  null ;
  }

  /**
   * Returns the scale type indicated in XML, or null if the special 'none' value was found.
   * Important: these values need to be in sync with GenericDraweeHierarchy styleable attributes.
   */
@Nullable
 private static ScaleType getScaleTypeFromXml(int scaleTypeVal) {
   switch (scaleTypeVal) {
     case -1: // none
       return null;
     case 0: // fitXY
       return ScaleType.FIT_XY;
     case 1: // fitStart
       return ScaleType.FIT_START;
     case 2: // fitCenter
       return ScaleType.FIT_CENTER;
     case 3: // fitEnd
       return ScaleType.FIT_END;
     case 4: // center
       return ScaleType.CENTER;
     case 5: // centerInside
       return ScaleType.CENTER_INSIDE;
     case 6: // centerCrop
       return ScaleType.CENTER_CROP;
     case 7: // focusCrop
       return ScaleType.FOCUS_CROP;
     case 8: // fitBottomStart
       return ScaleType.FIT_BOTTOM_START;
     default:
       // this method is supposed to be called only when XML attribute is specified.
       throw new RuntimeException("XML attribute not specified!");
   }
//  }
}
}
